#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define COMMAND_SIZE 1024
#define FORMAT "[%s@%s %s]# "

// 下面是shell定义的全局数据

#define MAXARGC 128
char *g_argv[MAXARGC];
int g_argc = 0; 

//获取用户名
const char *GetUserName(){
    const char *name = getenv("USER");
    return name = NULL ? "None" : name;
}

const char *GetHostName(){
    const char *hostname = getenv("HOSTNAME");
    return hostname = NULL ? "None" : hostname;
}

    
const char *GetPwd(){
    const char *pwd = getenv("PWD");
    return pwd = NULL ? "None" : pwd;
}

// / /a/b/c
std::string DirName(const char *pwd)
{
#define  slash "/"
    std::string str = pwd;
    if(str == slash) return slash;
    int pos = str.rfind(slash);
    //int pos = str.find(slash);
    //pos = str.find(slash , pos+1 );
    if(pos == std::string::npos) return "error?";
    //rfind返回的是"/"的下标，所以+1跳过"/"
    return str.substr(pos+1);
    //return str.substr(pos);
}

void MakeCommandLine(char cmd_prompt[], int size){
    //#define FORMAT "[%s@%s %s]# "
    //snprintf(cmd_prompt,size,FORMAT,GetUserName(),GetHostName(),GetPwd());
    snprintf(cmd_prompt,size,FORMAT,GetUserName(),GetHostName(),DirName(GetPwd()).c_str());
}


void PrintCommandPrompt(){
    char prompt[COMMAND_SIZE];
    MakeCommandLine ( prompt  , sizeof(prompt));
    printf("%s",prompt);
    //刷新输出流
    fflush(stdout);
}

bool GetCommandLine(char *out,int size){
    // ls -a -l => "ls -a -l\n" 字符串
    char*c = fgets(out , size , stdin );
    if( c == NULL) return false;
    out[strlen(out)-1] = 0;
    //清理\n，在输入流中默认存在回车\n所以打印时会存在换行
    if(strlen(out) == 0) return false;

    return true;
}

// 3. 命令行分析 "ls -a -l" -> "ls" "-a" "-l"
bool CommandParse(char *commandline)
{
#define sep " "
    //#define MAXARGC 128
    //char *g_argv[MAXARGC];
    //int g_argc = 0; 
    g_argc = 0;
    g_argv[g_argc++] = strtok( commandline , sep);
    //strtok(nullptr , sep);nullptr表示继续上次分割操作
    while((bool)(g_argv[g_argc++] = strtok(nullptr , sep)));
    g_argc--;//始终会存在一个末尾0，末尾0是GetCommandLine中清理\n的替换
    
    return true;
}

void PrintArgv()
{
    for(int i = 0; g_argv[i]; i++)
    {
        printf("argv[%d]->%s\n", i, g_argv[i]);
    }
    printf("argc: %d\n", g_argc);
}

int Execute(){
    pid_t id = fork();
    if(id ==0 ){
        //我是子进程
        execvp(g_argv[0],g_argv);
        exit(1);
    }
    pid_t rid = waitpid(id, nullptr,0);
}

int main(){

    //const char *hostname = getenv("HOSTNAME");
    //printf("%s",hostname);
    //env | grep HOSTNAME  ， set | grep HOSTNAME，查询HOSTNAME时,前者在环境变量中查询，后者在内部查询，如果返回为null
    //如果要永久添加，可以在 ~/.bashrc 文件里面，添加这个 export HOSTNAME=$(hostname)
    //source ~/.bashrc
    while(true){ 
        // 1. 输出命令行提示符
        PrintCommandPrompt();

        // 2. 获取用户输入的命令
        char commandline[COMMAND_SIZE];
        if(! GetCommandLine(commandline, sizeof(commandline)))
           continue;
        //printf("%s,commandline)
        // 3. 命令行分析 "ls -a -l" -> "ls" "-a" "-l"
        CommandParse(commandline);
        //PrintArgv();

        // 4. 执行命令
         Execute();
    }
    return 0;
}
